/*
 * Copyright 2011 The Rusted Roof, LLC.
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *        http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */

package org.proteusframework.api.model;

import java.util.Collection;
import java.util.Map;

/**
 * Defines a collection of static versions supported by a plugin archetype. This collection is known at compile time
 * since the plugin archetype is the primordial source for plugin API versions. It is illogical for the plugin archetype
 * to support API versions 1 and 2, and have a plugin instance claim to support API version 3. If there is indeed an
 * API version 3, then the plugin archetype must authoritatively declare such version via its
 * <code>IVersionCollection</code>.
 *
 * @author Tacoma Four
 */
public interface IVersionCollection
{
    /**
     * Map of key-value metadata used to define the collection of API versions supported by the plugin archetype.
     *
     * @return Read-only map of arbitrary metadata properties used by the plugin archetype to convey additional
     *         information about its supported versions.
     */
    Map<String, String> getProperties();

    /**
     * Read the named property.
     *
     * @param key Name of the property to read
     * @return Property value assigned to the given key, or null if the key cannot be found
     */
    String getProperty(String key);

    /**
     * Determine if the version collection has a property with the given name.
     *
     * @param key Name of the property to look for
     * @return true, if the version collection has a value assigned to the given key
     */
    boolean hasProperty(String key);

    /**
     * Identifies the default qualified name that supports the requested API version. Presently, the default
     * is determined via the Java <code>ClassLoader</code>.
     *
     * @param version Version to locate
     * @return Default qualified name that implements the given API version
     * @throws NoSuchVersionException when no plugin instances support the requested version in the runtime environment
     */
    IQualifiedName getInterfaceQualifiedName(IVersion version) throws NoSuchVersionException;

    /**
     * Determine if the given version is installed in the runtime environment.
     *
     * @param version Version to locate
     * @return true, if one or more plugin instances of the given version are installed in the runtime environment
     */
    boolean isVersionInstalled(IVersion version);

    /**
     * Perform a manual registration of a plugin instance, formally declaring which version the instance supports. This
     * method should be rarely used; instead, follow the standard Java SPI architecture and formally declare plugin
     * instances via <code>META-INF/services/</code> entry.
     *
     * @param qualifiedName Qualified name being registered
     * @param versions      Collection of API versions supported by the qualified name
     */
    void registerVersion(IQualifiedName qualifiedName, Collection<IVersion> versions);

    /**
     * Identifies a complete collection of versions defined by the plugin archetype.
     *
     * @return Non-null collection of supported versions
     */
    Collection<IVersion> supportedVersions();

    /**
     * Obtains a versioned interface for the given version.
     *
     * @param version Version to obtain a versioned interface for.
     * @return Versioned interface that can either list or emit the signatures for the associated version
     * @throws NoSuchVersionException when version match exists within the collection
     */
    VersionedInterface getInterface(IVersion version) throws NoSuchVersionException;

    /**
     * Collection of versioned interface definitions.
     *
     * @return Immutable collectin of versioned interface definitions
     */
    Collection<VersionedInterface> getInterfaces();
}
